package Structures;


/**
 * Instancia los nodos para el grafo dirigido
 * @author Jeremy
 * @author Rodrigo  
 * @author Alexandre
 * @author Gabriel
 */
public class Node {
    
    private Object _element; //Elemento que contiene el nodo.
    private int _outDegree; //Define el grado de salida.
    private Edge _firstOutEdge; //Referencia a la primera arista de salida.
    private Node _prevNode, _nextNode; //Referencia al nodo anterior y siguiente.
    private boolean _tour; //Define si el nodo ha sido recorrido 
                         //(para metodos de recorridos por anchura y profundidad).
    private int _distance; //Almacena la distancia al nodo fuente, (para dijkstra).
    
    /**
     * Construye un nuevo nodo con su elemento y el punto de las coordenadas graficas
     * @param pElement Dato para el nodo.
     */
    public Node (Object pElement) {
        this._distance = 0;
        this._element = pElement;
        _outDegree = 0;
        _firstOutEdge = null;
        _prevNode = null;
        _nextNode = null;
        _tour = false;
    }
        
    //////////////////////////////Getters y setters/////////////////////////////
    /**
     * Obtiene el elemento o dato del nodo.
     * @return Dato del nodo
     */
    public Object getElement() {
        return _element;
    }

    /**
     * Establece el dato para el nodo.
     * @param pElement Elemento para establecer al nodo
     */
    public void setElement(Object pElement) {
        this._element = pElement;
    }

    /**
     * Obtiene el grado de salida del nodo.
     * @return Grado de salida
     */
    public int getOutDegree() {
        return _outDegree;
    }

    /**
     * Obtiene la primer arista conectada al nodo, de la lista de aristas.
     * @return Primera conexion de la lista de aristas de este nodo
     */
    public Edge getFirstOutEdge() {
        return _firstOutEdge;
    }

    /**
     * Obtiene el nodo previo en la lista de nodos del grafo.
     * @return Nodo anterior
     */
    public Node getPrevNode() {
        return _prevNode;
    }

    /**
     * Obtiene el nodo siguiente el la lista de nodos del grafo.
     * @return Nodo siguiente
     */
    public Node getNextNode() {
        return _nextNode;
    }

    /**
     * Retorna un buleano que representa si el nodo ha sido recorrido o no
     * (Para los metodos de recorridos del grafo).
     * @return true si el nodo ya ha sido recorrido, false de lo contrario
     */
    public boolean isTour() {
        return _tour;
    }



    /**
     * Obtiene la distancia al nodo fuente (para dijkstra).
     * @return Distancia del mismo al nodo requerido por dijkstra
     */
    public int getDistance() {
        return _distance;
    }

    /**
     * establece el grado de salida.
     * @param pOutDegree Grado para establecer
     */
    public void setOutDegree(int pOutDegree) {
        this._outDegree = pOutDegree;
    }

    /**
     * Establece la arista para el inicio de la lista de aristas de salida del nodo.
     * @param pFirstOutEdge Arista para establecer
     */
    public void setFirstOutEdge(Edge pFirstOutEdge) {
        this._firstOutEdge = pFirstOutEdge;
    }

    /**
     * Establece el nodo anterior en la conexion de este para la lista de nodos del grafo.
     * @param pPrevNode Nodo para establecer
     */
    public void setPrevNode(Node pPrevNode) {
        this._prevNode = pPrevNode;
    }

    /**
     * Establece el nodo siguiente para la conexion de este para la lista de nodos del grafo.
     * @param pNextNode Nodo para establcer
     */
    public void setNextNode(Node pNextNode) {
        this._nextNode = pNextNode;
    }

    /**
     * Establece el buleano usado para los recorridos, para saber si el nodo ha sido recorrido o no.
     * @param pTour false o true
     */
    public void setTour(boolean pTour) {
        this._tour = pTour;
    }


    /**
     * Establece la distancia desde el nodo casa (para dijkstra).
     * @param pDistance Distancia para establecer
     */
    public void setDistance(int pDistance) {
        this._distance = pDistance;
    }
    ////////////////////////////////////////////////////////////////////////////
    
    /**
     * Metodo para ser usado con el algoritmo dijkstra, dice si un nodo se
     * encuentra ya en una cola de prioridad.
     * @param pQueue
     * @return true si el nodo se encuentra en la cola, de lo contrario retorna false
     */
    public boolean isInQueue (PriorityQueue pQueue) {
        for (SLLNode n = pQueue.getFirst(); n != null; n = n.getSucc()) {
            Node nN = (Node) n.getElement();
            if (nN._element.equals(this._element)) {
                return true;
            }
        }
        return false;
    }
}
